/***
 * 
 *  ASMEX by RiskCare Ltd.
 * 
 * This source is copyright (C) 2002 RiskCare Ltd. All rights reserved.
 * 
 * Disclaimer:
 * This code is provided 'as is', with absolutely no warranty expressed or
 * implied.  Any use of this code is at your own risk.
 *   
 * You are hereby granted the right to redistribute this source unmodified
 * in its original archive. 
 * You are hereby granted the right to use this code, or code based on it,
 * provided that you acknowledge RiskCare Ltd somewhere in the documentation
 * of your application. 
 * You are hereby granted the right to distribute changes to this source, 
 * provided that:
 * 
 * 1 -- This copyright notice is retained unchanged 
 * 2 -- Your changes are clearly marked 
 * 
 * Enjoy!
 * 
 * --------------------------------------------------------------------
 * 
 * If you use this code or have comments on it, please mail me at 
 * support@jbrowse.com or ben.peterson@riskcare.com
 * 
 */

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Reflection;
using System.IO;

namespace Asmex
{

	/// <summary>
	/// Dialog that selects an assembly from the GAC.  It enumerates assemblies by actually looking
	/// for DLLs within the GAC directory.  Later versions of the framework will probably provide
	/// a better way to do this.
	/// </summary>
	internal class GACPicker : System.Windows.Forms.Form
	{
		private System.ComponentModel.Container components = null;
		private System.Windows.Forms.Button btnOK;
		private System.Windows.Forms.Button btnCxl;
		private System.Windows.Forms.ListView lvAsms;

		Assembly _assembly;
		private System.Windows.Forms.ColumnHeader AssemblyName;
		private System.Windows.Forms.ColumnHeader Version;
		private System.Windows.Forms.ColumnHeader Culture;
		ArrayList _asms;

		public GACPicker()
		{
			InitializeComponent();

			_asms = new ArrayList();
		}

		public Assembly Assembly{get{return _assembly;}}

		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}


		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(GACPicker));
			this.btnOK = new System.Windows.Forms.Button();
			this.btnCxl = new System.Windows.Forms.Button();
			this.lvAsms = new System.Windows.Forms.ListView();
			this.AssemblyName = new System.Windows.Forms.ColumnHeader();
			this.Version = new System.Windows.Forms.ColumnHeader();
			this.Culture = new System.Windows.Forms.ColumnHeader();
			this.SuspendLayout();
			// 
			// btnOK
			// 
			this.btnOK.Anchor = (System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left);
			this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK;
			this.btnOK.Location = new System.Drawing.Point(176, 448);
			this.btnOK.Name = "btnOK";
			this.btnOK.TabIndex = 1;
			this.btnOK.Text = "OK";
			this.btnOK.Click += new System.EventHandler(this.btnOK_Click);
			// 
			// btnCxl
			// 
			this.btnCxl.Anchor = (System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left);
			this.btnCxl.DialogResult = System.Windows.Forms.DialogResult.Cancel;
			this.btnCxl.Location = new System.Drawing.Point(296, 448);
			this.btnCxl.Name = "btnCxl";
			this.btnCxl.TabIndex = 2;
			this.btnCxl.Text = "Cancel";
			// 
			// lvAsms
			// 
			this.lvAsms.Anchor = (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
				| System.Windows.Forms.AnchorStyles.Left) 
				| System.Windows.Forms.AnchorStyles.Right);
			this.lvAsms.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
																					 this.AssemblyName,
																					 this.Version,
																					 this.Culture});
			this.lvAsms.Location = new System.Drawing.Point(8, 8);
			this.lvAsms.Name = "lvAsms";
			this.lvAsms.Size = new System.Drawing.Size(528, 432);
			this.lvAsms.TabIndex = 3;
			this.lvAsms.View = System.Windows.Forms.View.Details;
			this.lvAsms.DoubleClick += new System.EventHandler(this.btnOK_Click);
			// 
			// AssemblyName
			// 
			this.AssemblyName.Text = "Assembly Name";
			this.AssemblyName.Width = 180;
			// 
			// Version
			// 
			this.Version.Text = "Version";
			this.Version.Width = 100;
			// 
			// Culture
			// 
			this.Culture.Text = "Culture";
			this.Culture.Width = 120;
			// 
			// GACPicker
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.CancelButton = this.btnCxl;
			this.ClientSize = new System.Drawing.Size(544, 483);
			this.Controls.AddRange(new System.Windows.Forms.Control[] {
																		  this.lvAsms,
																		  this.btnCxl,
																		  this.btnOK});
			this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
			this.Name = "GACPicker";
			this.Text = "Select Asssembly from GAC";
			this.Load += new System.EventHandler(this.GACPicker_Load);
			this.ResumeLayout(false);

		}
		#endregion

		private void btnOK_Click(object sender, System.EventArgs e)
		{
			ListViewItem it = lvAsms.SelectedItems[0];

			if (it == null)
			{
				MessageBox.Show("Please select an assembly.");
				return;
			}

			try
			{
				_assembly = Assembly.Load(it.SubItems[3].Text);
			}
			catch(Exception ee)
			{
				MessageBox.Show("Unable to load selected assembly!");
				return;
			}

			this.DialogResult = DialogResult.OK;
			this.Close();

		}

		private void GACPicker_Load(object sender, System.EventArgs e)
		{
			string root = Environment.SystemDirectory;
			
			int n = root.LastIndexOf("\\");
			root = root.Substring(0, n);
			root += "\\Assembly\\GAC";

			try
			{
				RecurseDirs(root);
			}
			catch(Exception ee)
			{
				MessageBox.Show("Unable to enumerate assemblies.  Does this account have permission to read %systemroot%\\system32\\assemblies?");
			}

			foreach (Assembly asm in _asms)
			{
				lvAsms.Items.Add(new ListViewItem(
					new string[]{ 
									asm.GetName().Name,
									asm.GetName().Version.ToString(),
									asm.GetName().CultureInfo.Name,
									asm.FullName
								}
					));
			}

            root = Environment.SystemDirectory;

            n = root.LastIndexOf("\\");
            root = root.Substring(0, n);
            root += "\\Microsoft.NET\\Assembly";

            try
            {
                RecurseDirs(root);
            }
            catch (Exception ee)
            {
                MessageBox.Show("Unable to enumerate assemblies.  Does this account have permission to read %systemroot%\\system32\\assemblies?");
            }

            foreach (Assembly asm in _asms)
            {
                lvAsms.Items.Add(new ListViewItem(
                    new string[]{ 
									asm.GetName().Name,
									asm.GetName().Version.ToString(),
									asm.GetName().CultureInfo.Name,
									asm.FullName
								}
                    ));
            }
        }

		void RecurseDirs(string dir)
		{
			Assembly asm;
			string[] files = Directory.GetFiles(dir);

			for(int i=0;i<files.Length;++i)
			{
				asm = null;

				try
				{
					asm = Assembly.LoadFrom(files[i]);
				}
				catch(Exception e){}
				
				if (asm != null)
				{
					_asms.Add(asm);
				}
			}

			string[] dirs = Directory.GetDirectories(dir);

			for(int i=0; i< dirs.Length;++i)
			{
				RecurseDirs(dirs[i]);
			}
		}
	}
	
}